跳到主要内容

Linux 的 proc 目录 - 进程属性

proc 目录是什么?

Linux 系统上的 /proc 目录存储的是当前内核运行状态的一系列特殊文件,用户可以通过这些文件查看有关系统硬件及当前正在运行进程的信息,甚至可以通过更改其中某些文件来改变内核的运行状态。

不过注意,/proc 目录是一个虚拟文件系统,其中有些文件虽然使用查看命令查看时会返回大量信息,但文件本身的大小却会显示为 0 字节。此外,这些特殊文件中大多数文件的时间及日期属性通常为当前系统时间和日期,这跟它们随时会被刷新(存储于 RAM 中)有关。

这些文件通常会按照相关性进行分类存储于不同的目录甚至子目录中,如 /proc/scsi 目录中存储的就是当前系统上所有 SCSI 设备的相关信息,/proc/N 中存储的则是系统当前正在运行的进程的相关信息,其中 N 为正在运行的进程(可以想象得到,在某进程结束后其相关目录则会消失)。

如下所示:

dr-xr-xr-x  9 root      root         0 Feb 13 17:36 1
dr-xr-xr-x 9 alsritter alsritter 0 Feb 13 19:50 176
dr-xr-xr-x 9 alsritter alsritter 0 Feb 13 19:50 211
dr-xr-xr-x 2 root root 0 Feb 13 19:50 acpi
-r--r--r-- 1 root root 0 Feb 13 19:50 buddyinfo
dr-xr-xr-x 4 root root 0 Feb 13 19:50 bus
-r--r--r-- 1 root root 0 Feb 13 19:50 crypto
-r--r--r-- 1 root root 0 Feb 13 19:50 devices
-r--r--r-- 1 root root 0 Feb 13 19:50 diskstats
-r--r--r-- 1 root root 0 Feb 13 19:50 dma
dr-xr-xr-x 4 root root 0 Feb 13 19:50 driver
-r--r--r-- 1 root root 0 Feb 13 19:50 execdomains
-r--r--r-- 1 root root 0 Feb 13 17:36 filesystems
dr-xr-xr-x 11 root root 0 Feb 13 19:50 fs

大多数虚拟文件可以使用文件查看命令如 cat、more 或者 less 进行查看

如果想快速的查看非进程文件夹可以使用

$ find /proc/ -maxdepth 1 ! -regex '.*/[0-9]*'

然后会列出 /proc 目录中一些进程相关的目录,每个目录中是当程本身相关信息的文件。

进程文件夹的内容

下面列一个进程文件夹(名称为数字的文件夹)里面的内容,这些内容可以在 man 文档里面看到

$ man proc

随便开一个进程(这里是 mc 命令),下面对这些常见文件做出说明。

$ ll /proc/1505

total 0
-r--r--r-- 1 alsritter alsritter 0 Feb 13 20:12 arch_status
dr-xr-xr-x 2 alsritter alsritter 0 Feb 13 20:12 attr
-r-------- 1 alsritter alsritter 0 Feb 13 20:12 auxv
-r--r--r-- 1 alsritter alsritter 0 Feb 13 20:12 cgroup
--w------- 1 alsritter alsritter 0 Feb 13 20:12 clear_refs
-r--r--r-- 1 alsritter alsritter 0 Feb 13 20:12 cmdline
-rw-r--r-- 1 alsritter alsritter 0 Feb 13 20:12 comm
-rw-r--r-- 1 alsritter alsritter 0 Feb 13 20:12 coredump_filter
-r--r--r-- 1 alsritter alsritter 0 Feb 13 20:12 cpuset
lrwxrwxrwx 1 alsritter alsritter 0 Feb 13 20:12 cwd -> /home/alsritter
-r-------- 1 alsritter alsritter 0 Feb 13 20:12 environ
lrwxrwxrwx 1 alsritter alsritter 0 Feb 13 20:12 exe -> /usr/bin/mc
dr-x------ 2 alsritter alsritter 0 Feb 13 20:12 fd
dr-x------ 2 alsritter alsritter 0 Feb 13 20:12 fdinfo
-rw-r--r-- 1 alsritter alsritter 0 Feb 13 20:12 gid_map
-r-------- 1 alsritter alsritter 0 Feb 13 20:12 io
-r--r--r-- 1 alsritter alsritter 0 Feb 13 20:12 limits
dr-x------ 2 alsritter alsritter 0 Feb 13 20:12 map_files
-r--r--r-- 1 alsritter alsritter 0 Feb 13 20:12 maps
-rw------- 1 alsritter alsritter 0 Feb 13 20:12 mem
-r--r--r-- 1 alsritter alsritter 0 Feb 13 20:11 mountinfo
-r--r--r-- 1 alsritter alsritter 0 Feb 13 20:12 mounts
-r-------- 1 alsritter alsritter 0 Feb 13 20:12 mountstats
dr-xr-xr-x 66 alsritter alsritter 0 Feb 13 20:12 net
dr-x--x--x 2 alsritter alsritter 0 Feb 13 20:12 ns
-rw-r--r-- 1 alsritter alsritter 0 Feb 13 20:12 oom_adj
-r--r--r-- 1 alsritter alsritter 0 Feb 13 20:12 oom_score
-rw-r--r-- 1 alsritter alsritter 0 Feb 13 20:12 oom_score_adj
-r-------- 1 alsritter alsritter 0 Feb 13 20:12 pagemap
-r-------- 1 alsritter alsritter 0 Feb 13 20:12 personality
-rw-r--r-- 1 alsritter alsritter 0 Feb 13 20:12 projid_map
lrwxrwxrwx 1 alsritter alsritter 0 Feb 13 20:12 root -> /
-rw-r--r-- 1 alsritter alsritter 0 Feb 13 20:12 sched
-r--r--r-- 1 alsritter alsritter 0 Feb 13 20:12 schedstat
-rw-r--r-- 1 alsritter alsritter 0 Feb 13 20:12 setgroups
-r--r--r-- 1 alsritter alsritter 0 Feb 13 20:12 smaps
-r--r--r-- 1 alsritter alsritter 0 Feb 13 20:12 smaps_rollup
-r-------- 1 alsritter alsritter 0 Feb 13 20:12 stack
-r--r--r-- 1 alsritter alsritter 0 Feb 13 20:12 stat
-r--r--r-- 1 alsritter alsritter 0 Feb 13 20:12 statm
-r--r--r-- 1 alsritter alsritter 0 Feb 13 20:12 status
-r-------- 1 alsritter alsritter 0 Feb 13 20:12 syscall
dr-xr-xr-x 3 alsritter alsritter 0 Feb 13 20:12 task
-r--r--r-- 1 alsritter alsritter 0 Feb 13 20:12 timers
-rw-rw-rw- 1 alsritter alsritter 0 Feb 13 20:12 timerslack_ns
-rw-r--r-- 1 alsritter alsritter 0 Feb 13 20:12 uid_map
-r--r--r-- 1 alsritter alsritter 0 Feb 13 20:12 wchan

cmdline 启动命令

启动当前进程的完整命令,注意僵尸进程目录中的此文件不包含任何信息;

$ more /proc/1505/cmdline
mc

cwd 指向当前进程运行目录

cwd 目录指向当前进程运行目录

$ ll /proc/1505/cwd
lrwxrwxrwx 1 alsritter alsritter 0 Feb 13 20:12 /proc/1505/cwd -> /home/alsritter

environ 进程的环境变量

当前进程的环境变量列表,彼此间用空字符(NULL)隔开;变量用大写字母表示,其值用小写字母表示;

$ more /proc/1505/environ
HOSTTYPE=x86_64/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/lib/wsl/lib

exe 指向执行文件

指向启动当前进程的可执行文件(完整路径)的符号链接,通过 /proc/N/exe 可以启动当前进程的一个拷贝;

ll /proc/1505/exe
lrwxrwxrwx 1 alsritter alsritter 0 Feb 13 20:12 /proc/1505/exe -> /usr/bin/mc

fd 文件描述符

这是个目录,包含当前进程打开的每一个文件的文件描述符(file descriptor),这些文件描述符是指向实际文件的一个符号链接;

$ ll /proc/1505/fd
total 0
lrwx------ 1 alsritter alsritter 64 Feb 13 21:02 0 -> /dev/pts/3
lrwx------ 1 alsritter alsritter 64 Feb 13 21:02 1 -> /dev/pts/3
lrwx------ 1 alsritter alsritter 64 Feb 13 21:02 2 -> /dev/pts/3
lrwx------ 1 alsritter alsritter 64 Feb 13 21:02 3 -> /dev/tty
lr-x------ 1 alsritter alsritter 64 Feb 13 21:02 4 -> 'pipe:[26063]'
l-wx------ 1 alsritter alsritter 64 Feb 13 21:02 5 -> 'pipe:[26063]'
lrwx------ 1 alsritter alsritter 64 Feb 13 21:02 6 -> /dev/ptmx
lrwx------ 1 alsritter alsritter 64 Feb 13 21:02 7 -> /dev/pts/4
lr-x------ 1 alsritter alsritter 64 Feb 13 21:02 8 -> 'pipe:[26066]'
l-wx------ 1 alsritter alsritter 64 Feb 13 21:02 9 -> 'pipe:[26066]'
$

limits 进程使用的受限资源

当前进程所使用的每一个受限资源的软限制、硬限制和管理单元,此文件仅可由实际启动当前进程的 UID 用户读取;(2.6.24 以后的内核版本支持此功能);

$ more /proc/1505/limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 8388608 unlimited bytes
Max core file size 0 unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 50801 50801 processes
Max open files 1024 4096 files
Max locked memory 65536 65536 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 50801 50801 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
$

maps 内存映射区域

当前进程关联到的每个可执行文件和库文件在内存中的映射区域及其访问权限所组成的列表;

$ more /proc/1505/maps
563f89220000-563f89239000 r--p 00000000 08:20 181809 /usr/bin/mc
563f89239000-563f892e3000 r-xp 00019000 08:20 181809 /usr/bin/mc
563f892e3000-563f89315000 r--p 000c3000 08:20 181809 /usr/bin/mc
563f89316000-563f8931c000 r--p 000f5000 08:20 181809 /usr/bin/mc
563f8931c000-563f89320000 rw-p 000fb000 08:20 181809 /usr/bin/mc
563f89320000-563f89355000 rw-p 00000000 00:00 0
563f89370000-563f89415000 rw-p 00000000 00:00 0 [heap]
7f9614ec1000-7f9614ec4000 r--p 00000000 08:20 59350 /usr/lib/x86_64-linux-gnu/libnss_files-2.31.so
7f9614ec4000-7f9614ecb000 r-xp 00003000 08:20 59350 /usr/lib/x86_64-linux-gnu/libnss_files-2.31.so
7f9614ecb000-7f9614ecd000 r--p 0000a000 08:20 59350 /usr/lib/x86_64-linux-gnu/libnss_files-2.31.so
......
$

mem 占用的内存空间

当前进程所占用的内存空间,由 open、read 和 lseek 等系统调用使用,不能被用户读取;

root 进程运行根目录

指向当前进程运行根目录的符号链接,在 Unix 和 Linux 系统上,通常采用 chroot 命令使每个进程运行于独立的根目录;

$ ll /proc/1505/root
lrwxrwxrwx 1 alsritter alsritter 0 Feb 13 20:12 /proc/1505/root -> /
$

chroot 命令用来在指定的根目录下运行指令。chroot,即 change root directory (更改 root 目录)。在 linux 系统中,系统默认的目录结构都是以 /,即是以根 (root) 开始的。而在使用 chroot 之后,系统的目录结构将以指定的位置作为 / 位置。

在经过 chroot 命令之后,系统读取到的目录和文件将不在是旧系统根下的而是新根下(即被指定的新的位置)的目录结构和文件,因此它带来的好处大致有以下3个:

  • 增加了系统的安全性,限制了用户的权力
  • 建立一个与原系统隔离的系统目录结构,方便用户的开发
  • 切换系统的根目录位置,引导 Linux 系统启动以及急救系统等

stat 进程的状态信息

当前进程的状态信息,包含一系统格式化后的数据列,可读性差,通常由 ps 命令使用;

$ more /proc/1505/stat
1505 (mc) S 291 1505 291 34819 1505 4210688 863 78 15 0 7 5 0 0 20 0 1 0 929726 19849216 1929 18446744073709551615 94830
883737600 94830884430501 140731815574048 0 0 0 0 0 134287362 1 0 0 17 2 0 0 0 0 0 94830884643920 94830884681984 94830885
011456 140731815576040 140731815576043 140731815576043 140731815579628 0
$

status 进程的状态信息

与stat所提供信息类似,但可读性较好,如下所示,每行表示一个属性信息;其详细介绍请参见 proc 的 man 手册页;

$ more /proc/1505/status
Name: mc
Umask: 0022
State: S (sleeping)
Tgid: 1505
Ngid: 0
Pid: 1505
PPid: 291
TracerPid: 0
Uid: 1000 1000 1000 1000
Gid: 1000 1000 1000 1000
FDSize: 64
Groups: 4 20 24 25 27 29 30 44 46 117 1000 1001
NStgid: 1505
NSpid: 1505
NSpgid: 1505
NSsid: 291
VmPeak: 19388 kB
VmSize: 19384 kB
VmLck: 0 kB
VmPin: 0 kB
VmHWM: 7716 kB
VmRSS: 7716 kB
RssAnon: 1576 kB
RssFile: 6140 kB
RssShmem: 0 kB
VmData: 2880 kB
VmStk: 132 kB
VmExe: 680 kB
VmLib: 5248 kB
VmPTE: 72 kB
VmSwap: 0 kB
HugetlbPages: 0 kB
CoreDumping: 0
THP_enabled: 1
Threads: 1
SigQ: 0/50801
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000000
SigCgt: 0000000188011002
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 000001ffffffffff
CapAmb: 0000000000000000
NoNewPrivs: 0
Seccomp: 0
Seccomp_filters: 0
Speculation_Store_Bypass: thread vulnerable
Cpus_allowed: ff
Cpus_allowed_list: 0-7
Mems_allowed: 1
Mems_allowed_list: 0
voluntary_ctxt_switches: 241
nonvoluntary_ctxt_switches: 1

statm 占用内存信息

当前进程占用内存的状态信息,通常以 “页面”(page)表示;

$ more /proc/1505/statm
4846 1929 1535 170 0 753 0
$

杀掉内存占用较高的进程时可以通过检查这个(一般还是用 ps 去监控)

检查 man 文档

$ man proc
...
/proc/[pid]/statm
Provides information about memory usage, measured in pages.
The columns are:

size (1) total program size
(same as VmSize in /proc/[pid]/status)
resident (2) resident set size
(same as VmRSS in /proc/[pid]/status)
share (3) shared pages (i.e., backed by a file)
text (4) text (code)
lib (5) library (unused in Linux 2.6)
data (6) data + stack
dt (7) dirty pages (unused in Linux 2.6)

task 线程的相关信息

包含由当前进程所运行的每一个线程的相关信息,每个线程的相关信息文件均保存在一个由线程号(tid)命名的目录中,这类似于其内容类似于每个进程目录中的内容;(内核2.6版本以后支持此功能)

$ ll /proc/1505/task
total 0
dr-xr-xr-x 7 alsritter alsritter 0 Feb 13 21:54 1505
$

可以看到这个 mc 进程内部只有一个线程,就是它自己(这个 1505 文件夹里面就是当前进程的内容)

References

Linux proc目录详解